﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FinanSoft.Entities;
using FinanSoft.Utilities;
using System.Data.SqlClient;
using FinanSoft.BusinessLayer;

namespace FinanSoft.DataLayer
{
    class StoreRoomDataManager
    {
        #region Fields
        /// <summary>
        /// Atributo privado del tipo de la clase. Unica instancia de esta clase que existira
        /// </summary>
        private static StoreRoomDataManager _instance;
        #endregion

        #region Constructors
        /// <summary>
        /// Constructor privado de la clase para permitir la implementacion del patron singleton
        /// </summary>
        private StoreRoomDataManager()
        {

        }
        #endregion

        #region Methods
        /// <summary>
        /// Metodo que obtienen la instancia existente de la clase. Si esta aun no ha sido instanciada, la instancia.
        /// </summary>
        public static StoreRoomDataManager GetInstance()
        {
            if (_instance == null)
                _instance = new StoreRoomDataManager();
            return _instance;
        }

        /// <summary>
        /// Obtiene todas las bodegas registradas en la base de datos y las retorna como una lista
        /// </summary>
        /// <returns>El objeto lista de bodegas</returns>
        public List<StoreRoom> GetStoreRooms()
        {
            List<StoreRoom> storeList;

            try
            {
                storeList = new List<StoreRoom>();
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_GET_STORES;
                SqlParameter[] parameters = new SqlParameter[0];
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                while (result.Read())
                {
                    String code = (string)result[Constants.SP_COLUMN_GET_STORES_CODE];
                    String name = (string)result[Constants.SP_COLUMN_GET_STORES_NAME];
                    int id = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ID]);
                    Account sales = CatalogManager.GetInstance().GetAccount((int)result[Constants.SP_COLUMN_GET_STORES_SALES_ACCOUNT_ID]);
                    Account purchases = CatalogManager.GetInstance().GetAccount((int)result[Constants.SP_COLUMN_GET_STORES_PURCHASES_ACCOUNT_ID]);
                    Account inventory = CatalogManager.GetInstance().GetAccount((int)result[Constants.SP_COLUMN_GET_STORES_INVENTORY_ACCOUNT_ID]);
                    Account salesCost = CatalogManager.GetInstance().GetAccount((int)result[Constants.SP_COLUMN_GET_STORES_SALES_COST_ACCOUNT_ID]);

                    storeList.Add(new StoreRoom(id, code, name, sales, purchases, inventory, salesCost));
                }
                dataHelper.CloseReader();
                return storeList;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// Obtiene todas los articulos y con su bodega respectiva de acuerdo a la base de datos
        /// </summary>
        /// <returns>El objeto lista de datos</returns>
        public List<ItemStoreRoomInfo> GetBodegaArticulo()
        {
            List<ItemStoreRoomInfo> BodegaArticuloList;

            try
            {
                BodegaArticuloList = new List<ItemStoreRoomInfo>();
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_GET_STORES_ARTICLES;
                SqlParameter[] parameters = new SqlParameter[0];
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                while (result.Read())
                {
                    int idBodega = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_ID_STORES]);
                    int idArticulo = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_ID_ARTICLE]);
                    int idCuentaInventario = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_ID_COUNT_INVENT]);
                    int idCuentaCostoVentas = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_ID_COUNT_COST_SALE]);
                    int idCuentaCompras = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_ID_COUNT_BUY]);
                    int idCuentaVentas = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_ID_COUNT_SALE]);
                    int stock = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_STOCK]);
                    int comprometido = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_COMMITED]);
                    int solicitado = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_REQUESTED]);
                    int costoUnitario = System.Convert.ToInt32(result[Constants.SP_COLUMN_GET_STORES_ARTICLES_COST_UNIT]);


                    BodegaArticuloList.Add(new ItemStoreRoomInfo(idBodega, idCuentaInventario, idCuentaCostoVentas, idCuentaCompras, idCuentaVentas, stock, comprometido, solicitado, costoUnitario));
                }
                dataHelper.CloseReader();
                return BodegaArticuloList;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        


        /// <summary>
        /// Se encarga de registrar una nueva bodega en la base de datos
        /// </summary>
        /// <param name="newStorage"> El objeto bodega a registrar en la base</param>
        /// <returns>El entero que representa el Id de la bodega registrada</returns>
        public int RegisterStorage(StoreRoom newStorage)
        {
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_NEW_STORE;

                SqlParameter[] parameters = {new SqlParameter(Constants.SP_PARAM_NEW_STORE_CODE, newStorage.Code),
                                             new SqlParameter(Constants.SP_PARAM_NEW_STORE_NAME, newStorage.Name),
                                             new SqlParameter(Constants.SP_PARAM_NEW_STORE_SALES_ACCOUNT, newStorage.SalesAccount.AccountID),
                                             new SqlParameter(Constants.SP_PARAM_NEW_STORE_PURCHASES_ACCOUNT, newStorage.PurchasesAccount.AccountID),
                                             new SqlParameter(Constants.SP_PARAM_NEW_STORE_INVENTORY_ACCOUNT, newStorage.InventoryAccount.AccountID),
                                             new SqlParameter(Constants.SP_PARAM_NEW_STORE_SALES_COST_ACCOUNT, newStorage.SalesCostAccount.AccountID),};

                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);

                if (result.HasRows)
                {
                    result.Read();
                    int idBodega = Convert.ToInt32(result[Constants.SP_COLUMN_NEW_STORE_ID]);
                    return idBodega;
                }
                return -1;
            }
            catch (Exception ex)
            {
                return -1;
            }
        }

        /// <summary>
        /// Método que se encarga de modificar una bodega existente
        /// </summary>
        /// <param name="updatedStorage">Recibe el objeto bodega modificado</param>
        /// <returns>Retorna true si se logró con éxito, false si no</returns>
        public bool UpdateStorage(StoreRoom updatedStorage)
        {
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_EDIT_STORE;
                SqlParameter[] parameters = {new SqlParameter(Constants.SP_PARAM_EDIT_STORE_ID, updatedStorage.Id),
                                             new SqlParameter(Constants.SP_PARAM_EDIT_STORE_CODE, updatedStorage.Code),
                                             new SqlParameter(Constants.SP_PARAM_EDIT_STORE_NAME, updatedStorage.Name),
                                             new SqlParameter(Constants.SP_PARAM_EDIT_STORE_SALES_ACCOUNT, updatedStorage.SalesAccount.AccountID),
                                             new SqlParameter(Constants.SP_PARAM_EDIT_STORE_PURCHASES_ACCOUNT, updatedStorage.PurchasesAccount.AccountID),
                                             new SqlParameter(Constants.SP_PARAM_EDIT_STORE_INVENTORY_ACCOUNT, updatedStorage.InventoryAccount.AccountID),
                                             new SqlParameter(Constants.SP_PARAM_EDIT_STORE_SALES_COST_ACCOUNT, updatedStorage.SalesCostAccount.AccountID),};

                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// Elimina una bodega de la base de datos. El SP no elimina la bodega si tiene algún valor mayor a 0 en Stock,
        /// Comprometido o Solicitado, sin embargo no tira error, por lo que este debe verificarse en la capa de negocios.
        /// Si tiene algún documento asociado, el SP se cae y se debe atrapar el error en la excepción.
        /// </summary>
        /// <param name="store">Bodega que se desea eliminar</param>
        /// <returns>Dice si la operación fue exitosa</returns>
        public bool DeleteStoreRoom(StoreRoom store)
        {
            try
            {
                AppConfigReader appConfig = AppConfigReader.GetInstance();
                string spName = Constants.SP_NAME_DELETE_STORE_ROOM;
                SqlParameter[] parameters = {new SqlParameter(Constants.SP_PARAM_DELETE_STORE_ROOM_STORE_ID, store.Id)};
                SqlDataHelper dataHelper = new SqlDataHelper(appConfig.GetConnectionString(Constants.DB_CONN));
                SqlDataReader result = dataHelper.ExecuteStoredProcedure(spName, parameters);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        #endregion Methods
    }
}
